using Domain.Services;
using Domain.Entities;
using Domain.Entities.Enums;
using System;
using System.Collections.Generic;
using System.Configuration;

namespace Domain.Permissions
{
    public class PermissionManager
    {
        private User user;
        private bool canViewActiveUserlist;
        private bool canViewUserlist;
        private bool canViewProfiles;
        private bool canUseSearch;
        private bool isAdministrator;

        public PermissionManager(User user)
        {
            this.user = user;
        }

        public ForumPermissionManager CreateForumPermissionManager(Forum forum)
        {
            Permission permission = Permission.None;
            
            UserForumPermission userForumPermission = UserForumPermissionService.GetByUserIdAndForumId(user.Id, forum.Id);
            if (userForumPermission != null)
            {
                permission |= userForumPermission.Permissions;
            }
            
            foreach (Group group in user.Groups)
            {
                GroupForumPermission groupForumPermission = GroupForumPermissionService.GetByGroupIdAndForumId(group.Id, forum.Id);
                if (groupForumPermission != null)
                {
                    permission |= groupForumPermission.Permissions;
                }
            }
            
            return new ForumPermissionManager(permission);
        }

        public bool GetCanViewActiveUserList()
        {
            foreach (Group group in user.Groups)
            {
                if (group.CanViewActiveUserlist)
                {
                    canViewActiveUserlist = true;
                    break;
                }
            }
            return canViewActiveUserlist;
        }

        public bool GetCanViewUserlist()
        {
            foreach (Group group in user.Groups)
            {
                if (group.CanViewUserlist)
                {
                    canViewUserlist = true;
                    break;
                }
            }
            return canViewUserlist;
        }

        public bool GetCanViewProfiles()
        {
            foreach (Group group in user.Groups)
            {
                if (group.CanViewProfiles)
                {
                    canViewProfiles = true;
                    break;
                }
            }
            return canViewProfiles;
        }

        public bool GetCanUseSearch()
        {
            foreach (Group group in user.Groups)
            {
                if (group.CanUseSearch)
                {
                    canUseSearch = true;
                    break;
                }
            }
            return canUseSearch;
        }

        public bool IsGuest()
        {
            return user.Id == int.Parse(ConfigurationManager.AppSettings["GuestUserId"]);
        }

        public bool IsAdministrator()
        {
            foreach (Group group in user.Groups)
            {
                if (group.IsAdministratorGroup)
                {
                    isAdministrator = true;
                    break;
                }
            }
            return isAdministrator;
        }

        public IList<Topic> FilterReadableTopics(IList<Topic> topics)
        {
            List<Topic> filteredTopics = new List<Topic>();
            Dictionary<int, ForumPermissionManager> forumPermissionManagers =
                new Dictionary<int, ForumPermissionManager>();
            foreach (Topic topic in topics)
            {
                ForumPermissionManager forumPermissionManager;
                if (forumPermissionManagers.ContainsKey(topic.Forum.Id))
                {
                    forumPermissionManager = forumPermissionManagers[topic.Forum.Id];
                }
                else
                {
                    forumPermissionManager = CreateForumPermissionManager(topic.Forum);
                    forumPermissionManagers[topic.Forum.Id] = forumPermissionManager;
                }
                if (forumPermissionManager.Read)
                {
                    filteredTopics.Add(topic);
                }
            }
            return filteredTopics;
        }

        public IList<Message> FilterReadableMessages(IList<Message> messages)
        {
            List<Message> filteredMessages = new List<Message>();
            Dictionary<int, ForumPermissionManager> forumPermissionManagers =
                new Dictionary<int, ForumPermissionManager>();
            foreach (Message message in messages)
            {
                ForumPermissionManager forumPermissionManager;
                Forum forum = message.Topic.Forum;
                if (forumPermissionManagers.ContainsKey(forum.Id))
                {
                    forumPermissionManager = forumPermissionManagers[forum.Id];
                }
                else
                {
                    forumPermissionManager = CreateForumPermissionManager(forum);
                    forumPermissionManagers[forum.Id] = forumPermissionManager;
                }
                if (forumPermissionManager.Read
                    && (!message.ModeratorsOnly || forumPermissionManager.Moderate))
                {
                    filteredMessages.Add(message);
                }
            }
            return filteredMessages;
        }
    }
}
